AArch64: Introduce RAS handling
authorJeenu Viswambharan <[email protected]>
Wed, 4 Apr 2018 15:07:11 +0000 (16:07 +0100)
committerJeenu Viswambharan <[email protected]>
Fri, 4 May 2018 07:33:17 +0000 (08:33 +0100)
RAS extensions are mandatory for ARMv8.2 CPUs, but are also optional
extensions to base ARMv8.0 architecture.

This patch adds build system support to enable RAS features in ARM
Trusted Firmware. A boolean build option RAS_EXTENSION is introduced for
this.

With RAS_EXTENSION, an Exception Synchronization Barrier (ESB) is
inserted at all EL3 vector entry and exit. ESBs will synchronize pending
external aborts before entering EL3, and therefore will contain and
attribute errors to lower EL execution. Any errors thus synchronized are
detected via. DISR_EL1 register.

When RAS_EXTENSION is set to 1, HANDLE_EL3_EA_FIRST must also be set to 1.

Change-Id: I38a19d84014d4d8af688bd81d61ba582c039383a
Signed-off-by: Jeenu Viswambharan <[email protected]>
Makefile
bl31/aarch64/runtime_exceptions.S
docs/user-guide.rst
include/bl31/ea_handle.h
include/common/aarch64/asm_macros.S
include/lib/aarch64/arch.h
lib/el3_runtime/aarch64/context.S
make_helpers/defaults.mk

index 23b48e8f4be16cc2eb4a029273dec0e2a8416e77..c588931f9473e06d20431259802fff122066f962 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -388,6 +388,13 @@ ifneq (${SMCCC_MAJOR_VERSION},1)
     endif
 endif
 
+# For RAS_EXTENSION, require that EAs are handled in EL3 first
+ifeq ($(RAS_EXTENSION),1)
+    ifneq ($(HANDLE_EA_EL3_FIRST),1)
+        $(error For RAS_EXTENSION, HANDLE_EA_EL3_FIRST must also be 1)
+    endif
+endif
+
 ################################################################################
 # Process platform overrideable behaviour
 ################################################################################
@@ -525,6 +532,7 @@ $(eval $(call assert_boolean,NS_TIMER_SWITCH))
 $(eval $(call assert_boolean,PL011_GENERIC_UART))
 $(eval $(call assert_boolean,PROGRAMMABLE_RESET_ADDRESS))
 $(eval $(call assert_boolean,PSCI_EXTENDED_STATE_ID))
+$(eval $(call assert_boolean,RAS_EXTENSION))
 $(eval $(call assert_boolean,RESET_TO_BL31))
 $(eval $(call assert_boolean,SAVE_KEYS))
 $(eval $(call assert_boolean,SEPARATE_CODE_AND_RODATA))
@@ -574,6 +582,7 @@ $(eval $(call add_define,PL011_GENERIC_UART))
 $(eval $(call add_define,PLAT_${PLAT}))
 $(eval $(call add_define,PROGRAMMABLE_RESET_ADDRESS))
 $(eval $(call add_define,PSCI_EXTENDED_STATE_ID))
+$(eval $(call add_define,RAS_EXTENSION))
 $(eval $(call add_define,RESET_TO_BL31))
 $(eval $(call add_define,SEPARATE_CODE_AND_RODATA))
 $(eval $(call add_define,SMCCC_MAJOR_VERSION))
index 494ccd79723b1352f8de2e44c5dd1a9f613d9268..346cd3b313a5e56fccdfbc7e6b46cd80ae50b9af 100644 (file)
        .globl  fiq_aarch32
        .globl  serror_aarch32
 
+       /*
+        * Macro that prepares entry to EL3 upon taking an exception.
+        *
+        * With RAS_EXTENSION, this macro synchronizes pending errors with an ESB
+        * instruction. When an error is thus synchronized, the handling is
+        * delegated to platform EA handler.
+        *
+        * Without RAS_EXTENSION, this macro just saves x30, and unmasks
+        * Asynchronous External Aborts.
+        */
+       .macro check_and_unmask_ea
+#if RAS_EXTENSION
+       /* Synchronize pending External Aborts */
+       esb
+
+       /* Unmask the SError interrupt */
+       msr     daifclr, #DAIF_ABT_BIT
+
+       /*
+        * Explicitly save x30 so as to free up a register and to enable
+        * branching
+        */
+       str     x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR]
+
+       /* Check for SErrors synchronized by the ESB instruction */
+       mrs     x30, DISR_EL1
+       tbz     x30, #DISR_A_BIT, 1f
+
+       /* Save GP registers and restore them afterwards */
+       bl      save_gp_registers
+       mov     x0, #ERROR_EA_ESB
+       mrs     x1, DISR_EL1
+       bl      delegate_ea
+       bl      restore_gp_registers
+
+1:
+#else
+       /* Unmask the SError interrupt */
+       msr     daifclr, #DAIF_ABT_BIT
+
+       str     x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR]
+#endif
+       .endm
+
        /*
         * Handle External Abort by delegating to the platform's EA handler.
         * Once the platform handler returns, the macro exits EL3 and returns to
         * ---------------------------------------------------------------------
         */
        .macro  handle_sync_exception
-       /* Enable the SError interrupt */
-       msr     daifclr, #DAIF_ABT_BIT
-
-       str     x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR]
-
 #if ENABLE_RUNTIME_INSTRUMENTATION
        /*
         * Read the timestamp value and store it in per-cpu data. The value
         * ---------------------------------------------------------------------
         */
        .macro  handle_interrupt_exception label
-       /* Enable the SError interrupt */
-       msr     daifclr, #DAIF_ABT_BIT
-
-       str     x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR]
        bl      save_gp_registers
-
        /* Save the EL3 system registers needed to return from this exception */
        mrs     x0, spsr_el3
        mrs     x1, elr_el3
@@ -256,14 +290,17 @@ vector_entry sync_exception_aarch64
         * to a valid cpu context where the general purpose and system register
         * state can be saved.
         */
+       check_and_unmask_ea
        handle_sync_exception
        check_vector_size sync_exception_aarch64
 
 vector_entry irq_aarch64
+       check_and_unmask_ea
        handle_interrupt_exception irq_aarch64
        check_vector_size irq_aarch64
 
 vector_entry fiq_aarch64
+       check_and_unmask_ea
        handle_interrupt_exception fiq_aarch64
        check_vector_size fiq_aarch64
 
@@ -289,14 +326,17 @@ vector_entry sync_exception_aarch32
         * to a valid cpu context where the general purpose and system register
         * state can be saved.
         */
+       check_and_unmask_ea
        handle_sync_exception
        check_vector_size sync_exception_aarch32
 
 vector_entry irq_aarch32
+       check_and_unmask_ea
        handle_interrupt_exception irq_aarch32
        check_vector_size irq_aarch32
 
 vector_entry fiq_aarch32
+       check_and_unmask_ea
        handle_interrupt_exception fiq_aarch32
        check_vector_size fiq_aarch32
 
index aed54a63152660cd08ca703c5fc4da01fa2d63b5..880fe7d9b70215d9972e0470423cd950e1f96e66 100644 (file)
@@ -531,6 +531,15 @@ Common build options
    smc function id. When this option is enabled on Arm platforms, the
    option ``ARM_RECOM_STATE_ID_ENC`` needs to be set to 1 as well.
 
+-  ``RAS_EXTENSION``: When set to ``1``, enable Armv8.2 RAS features. RAS features
+   are an optional extension for pre-Armv8.2 CPUs, but are mandatory for Armv8.2
+   or later CPUs.
+
+   When ``RAS_EXTENSION`` is set to ``1``, ``HANDLE_EA_EL3_FIRST`` must also be
+   set to ``1``.
+
+   This option is disabled by default.
+
 -  ``RESET_TO_BL31``: Enable BL31 entrypoint as the CPU reset vector instead
    of the BL1 entrypoint. It can take the value 0 (CPU reset to BL1
    entrypoint) or 1 (CPU reset to BL31 entrypoint).
index 285132b7ebc8af97543b2db7357ca3c2555315d1..9dfe3e0a7ecdbeb355630b78d2cb35f90ce0780d 100644 (file)
@@ -15,4 +15,7 @@
 /* Synchronous External Abort received at Synchronous exception vector */
 #define ERROR_EA_SYNC          1
 
+/* External Abort synchronized by ESB instruction */
+#define ERROR_EA_ESB           2
+
 #endif /* __EA_HANDLE_H__ */
index 94a9df92d349106a759835c0882bb70f8d8298d2..7c8e643d1140c3bcd4634f1afac64f0b867ff673 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
        .space  SPINLOCK_ASM_SIZE
        .endm
 
+#if RAS_EXTENSION
+       .macro esb
+       .inst   0xd503221f
+       .endm
+#endif
+
 #endif /* __ASM_MACROS_S__ */
index a44694126309bd5d7388b7130cc1363bb2d626bd..5be4b4e9edbf8125b718a4dffc7b5e66e672c7d5 100644 (file)
 #define AMCGCR_EL0_CG1NC_LENGTH        U(8)
 #define AMCGCR_EL0_CG1NC_MASK  U(0xff)
 
+/*******************************************************************************
+ * RAS system registers
+ *******************************************************************************/
+#define DISR_EL1               S3_0_C12_C1_1
+#define DISR_A_BIT             31
+
 #endif /* __ARCH_H__ */
index 9a53b76c103311869200c7a2c0a683a94d06fc02..121ca4d30920c3620466165666e67e537d6d7791 100644 (file)
@@ -364,6 +364,16 @@ endfunc restore_gp_registers
 func restore_gp_registers_eret
        bl      restore_gp_registers
        ldr     x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR]
+
+#if IMAGE_BL31 && RAS_EXTENSION
+       /*
+        * Issue Error Synchronization Barrier to synchronize SErrors before
+        * exiting EL3. We're running with EAs unmasked, so any synchronized
+        * errors would be taken immediately; therefore no need to inspect
+        * DISR_EL1 register.
+        */
+       esb
+#endif
        eret
 endfunc        restore_gp_registers_eret
 
index 00ac12687b8a7c19d825bdfd041a406d628f52ec..791a9c0866a0b427c87885226e0bfb133c30ac5f 100644 (file)
@@ -124,6 +124,9 @@ PROGRAMMABLE_RESET_ADDRESS  := 0
 # Original format.
 PSCI_EXTENDED_STATE_ID         := 0
 
+# Enable RAS support
+RAS_EXTENSION                  := 0
+
 # By default, BL1 acts as the reset handler, not BL31
 RESET_TO_BL31                  := 0